/*
 * 文件名： CiticExpayServiceImpl.java
 * 
 * 工程名称: bis-service
 *
 * Gopay
 *
 * 创建日期： 2016年6月17日
 *
 * Copyright(C) 2016, by www.gopay.com.cn Inc.All rights reserved.
 *
 * 原始作者: 宣广海
 *
 */
package com.gopay.bis.service.bank.impl.expay;

import java.util.HashMap;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;

import com.gopay.bis.common.util.BankLogUtils;
import com.gopay.bis.manager.bank.expay.CiticExPayManage;
import com.gopay.bis.service.bank.sms.SmsSupportController;
import com.gopay.common.Result;
import com.gopay.common.constants.bank.BankContractConstants;
import com.gopay.common.constants.bank.QueryNeedCertConstants;
import com.gopay.common.constants.bank.CiticConstants;
import com.gopay.common.constants.proccode.ProcCodeConstants;
import com.gopay.common.domain.bank.ExPayBaseMessage;
import com.gopay.common.domain.bank.citic.expay.CiticExpay;
import com.gopay.common.domain.bank.citic.expay.CiticExpayErrorMessage;
import com.gopay.common.domain.bank.citic.expay.CiticExpayResMessage;
import com.gopay.common.domain.bank.citic.expay.certification.CiticExpayCerResMessage;
import com.gopay.common.domain.bank.citic.expay.pay.CiticExpayPayResMessage;
import com.gopay.common.domain.bank.citic.expay.query.CiticExpayQueryResMessage;
import com.gopay.common.domain.bank.citic.expay.refund.CiticExpayRefundResMessage;
import com.gopay.common.domain.bank.citic.expay.sign.CiticExpaySignResMessage;
import com.gopay.common.domain.bis.BisBankContractInfo;
import com.gopay.common.exception.GopayException;
import com.gopay.common.util.TransUtil;
import com.gopay.remote.bank.ExPayInteractRemoteService;

/**
 * 中信银行快捷支付业务实现处理类
 *
 * @author 宣广海
 *
 * @version
 *
 * @since 2016年6月17日
 */
public class CiticExpayServiceImpl implements ExPayInteractRemoteService {

    /**
     * 日志对象
     */
    private static Logger logger = LoggerFactory.getLogger(CiticExpayServiceImpl.class);
    /**
     * 发送短信，验证短信操作对象
     */
    private SmsSupportController smsController;
    /**
     * 注入对象
     */
    @Autowired
    private CiticExPayManage citicExPayManage;

    @Override
    public Result sign(ExPayBaseMessage baseMsg) {
        Result result = new Result(false);
        CiticExpay citicExpay = new CiticExpay();
        BeanUtils.copyProperties(baseMsg, citicExpay);
        try {
            // 验证是否已经签约
            BisBankContractInfo bisBankContractInfo = citicExPayManage.checkContract(citicExpay);
            if (bisBankContractInfo == null
                    || BankContractConstants.CONTRACT_CANCEL.equals(bisBankContractInfo.getContractState())) {
                // 没有签约信息，即首次签约，插入一条签约记录
                CiticExpayResMessage resMessage = (CiticExpayResMessage) citicExPayManage.sign(citicExpay);
                if (resMessage.isSuccess()) {
                    CiticExpaySignResMessage signresMsg = resMessage.getExpayMessage().getSignResMessage();
                    if (CiticConstants.EXPAY_RECODE_SUCCESS.equals(signresMsg.getRetCode())) {
                        // 签约记录不存在，插入一条签约记录
                        if (bisBankContractInfo == null) {
                            citicExpay.setAgrmtNo(signresMsg.getSignNo().trim());
                            citicExPayManage.createContract(citicExpay);
                            result.setModel("signNo", signresMsg.getSignNo().trim());
                        } else {
                            // 如果存在签约记录，但是失效，则重新签约后，更新原有的签约记录
                            citicExpay.setAgrmtNo(signresMsg.getSignNo());
                            citicExPayManage.againNewContract(citicExpay);
                            result.setModel("signNo", signresMsg.getSignNo().trim());
                        }
                    }
                }
            } else {
                // 返回签约号
                result.setModel("signNo", bisBankContractInfo.getContractNumber().trim());
            }
            result.setSuccess(true);
        } catch (GopayException e) {
            BankLogUtils.printServiceImplExceptionLog(e);
            result.setResultCode(e.getErrCode());
        } catch (Exception ex) {
            BankLogUtils.printServiceImplExceptionLog(ex);
            result.setResultCode(ProcCodeConstants.PROC_CODE_100E6076);
        }
        return result;
    }

    @Override
    public Result verify(ExPayBaseMessage baseMsg) {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public Result treatyQuery(ExPayBaseMessage baseMsg) {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public Result cancel(ExPayBaseMessage baseMsg) {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public Result payment(ExPayBaseMessage baseMsg) {
        Result result = new Result(false);
        CiticExpay citicExpay = new CiticExpay();
        BeanUtils.copyProperties(baseMsg, citicExpay);
        try {
            Result signResult = sign(citicExpay);
            if (signResult.isSuccess()) {
                citicExpay.setAgrmtNo((String) signResult.getModel("signNo"));
            } else {
                result.setResultCode(signResult.getResultCode());
                result.setSuccess(true);
                result.setOrderStatus(false);
                result.setDefaultModel(false);
                return result;
            }
            CiticExpayResMessage resMessage = (CiticExpayResMessage) citicExPayManage.payment(citicExpay);
            result.setDefaultModel(resMessage.isSuccess());
            CiticExpayPayResMessage payresMsg = resMessage.getExpayMessage().getPayResMessage();
            CiticExpayErrorMessage errorMsg = resMessage.getExpayMessage().getErrorMessage();
            Map<String, String> param = new HashMap<String, String>();
            if (resMessage.isSuccess() && payresMsg != null
                    && CiticConstants.EXPAY_RECODE_SUCCESS.equals(payresMsg.getRetCode())) {
                param.put("orderId", payresMsg.getSerialNo().trim());
                param.put("amt", TransUtil.amountConvert2Yuan(payresMsg.getAmount()));
                param.put("cardType", "Unknown");
                param.put("notifyNum", "1");
                param.put("payStatus", "00");
                param.put("retCode", "00");
                param.put("retMsg", "验签成功");
                param.put("isFront", String.valueOf(false));
                result.setModel("isNotifyCashier", param);
                result.setSuccess(true);
                result.setOrderStatus(true);
            } else {
                param.put("orderId", baseMsg.getOrderId());
                param.put("amt", baseMsg.getAmount().toString());
                param.put("cardType", "Unknown");
                param.put("notifyNum", "1");
                param.put("payStatus", "01");
                param.put("retCode", "01");
                // 记录数据库失败信息 add by zhengxue 20170313
                String errorMessage = resMessage.getExpayMessage().getErrorMessage().getRetMsg();
                param.put("retMsg", StringUtils.isEmpty(errorMessage) ? "交易失败" : errorMessage);
                param.put("isFront", String.valueOf(false));
                result.setModel("isNotifyCashier", param);
                result.setSuccess(true);
                result.setOrderStatus(false);
                result.setBankRetCode(resMessage.getBankRetCode());

                if (errorMsg != null) {
                    String payCode = errorMsg.getRetCode();
                    if ("1001".equals(payCode) || "1002".equals(payCode) || "1510".equals(payCode)) {
                        // 1001-签约协议号无效 1002-网上支付签约状态不正确 1510-签约异常
                        citicExPayManage.updateContractByCardNo(citicExpay, "02");
                        logger.error("中信借记卡快捷支付-因解约问题导致支付失败，返回的错误码：" + payCode + ",更新银行用户签约信息表状态为：02-签约作废");
                    }
                }
            }
        } catch (GopayException e) {
            BankLogUtils.printServiceImplExceptionLog(e);
            result.setResultCode(e.getErrCode());
        } catch (Exception ex) {
			BankLogUtils.printServiceImplExceptionLog(ex);
			result.setResultCode(ProcCodeConstants.PROC_CODE_100E6057);
		}
        return result;
    }

    @Override
    public Result refund(ExPayBaseMessage baseMsg) {
        Result result = new Result(false);
        CiticExpay message = new CiticExpay();
        BeanUtils.copyProperties(baseMsg, message);
        try {
            CiticExpayResMessage resMessage = (CiticExpayResMessage) citicExPayManage.refund(message);
            result.setDefaultModel(resMessage.isSuccess());
            CiticExpayRefundResMessage refResMsg = resMessage.getExpayMessage().getRedfunResMessage();
            Map<String, String> param = new HashMap<String, String>();
            if (resMessage.isSuccess() && refResMsg != null
                    && CiticConstants.EXPAY_RECODE_SUCCESS.equals(refResMsg.getRetCode())) {
                param.put("orderId", refResMsg.getSerialNo().trim());
                param.put("amt", TransUtil.amountConvert2Yuan(refResMsg.getAmount()));
                param.put("cardType", "Unknown");
                param.put("notifyNum", "1");
                param.put("payStatus", "00");
                param.put("retCode", "00");
                param.put("retMsg", "验签成功");
                param.put("isFront", String.valueOf(false));
                result.setModel("isNotifyCashier", param);
                result.setSuccess(true);
                result.setOrderStatus(true);
            } else {
                param.put("orderId", baseMsg.getOrderId());
                param.put("amt", baseMsg.getAmount().toString());
                param.put("cardType", "Unknown");
                param.put("notifyNum", "1");
                param.put("payStatus", "01");
                param.put("retCode", "01");
                // 记录数据库失败信息 add by zhengxue 20170313
                String errorMessage = resMessage.getExpayMessage().getErrorMessage().getRetMsg();
                param.put("retMsg", StringUtils.isEmpty(errorMessage) ? errorMessage : refResMsg.getRetMsg());
                param.put("isFront", String.valueOf(false));
                result.setModel("isNotifyCashier", param);
                result.setSuccess(true);
                result.setOrderStatus(false);
            }
        } catch (GopayException e) {
            BankLogUtils.printServiceImplExceptionLog(e);
            result.setResultCode(e.getErrCode());
        } catch (Exception ex) {
            BankLogUtils.printServiceImplExceptionLog(ex);
            result.setResultCode(ProcCodeConstants.PROC_CODE_100E6087);
        }
        return result;
    }

    @Override
    public Result queryOrder(ExPayBaseMessage baseMsg) {
        Result result = new Result(false);
        CiticExpay citicExpay = new CiticExpay();
        BeanUtils.copyProperties(baseMsg, citicExpay);
        try {
            CiticExpayResMessage resMessage = (CiticExpayResMessage) citicExPayManage.queryOrder(citicExpay);

//            if (resMessage.isSuccess()) {
//
//                CiticExpayQueryResMessage queryresMsg = resMessage.getExpayMessage().getQueryResMessage();
//
//                if (null != queryresMsg) {
//                    result.setDefaultModel(queryresMsg);
//                }
//
//            } 
            
            //因快捷支付退款需要获取Error对象，所有均作为返回对象
            result.setDefaultModel(resMessage);
            result.setSuccess(true);
            result.setBankRetCode(resMessage.getBankRetCode());//add by liuyu, 20170803, 快捷支付API失败通知
        } catch (GopayException e) {
            BankLogUtils.printServiceImplExceptionLog(e);
            result.setResultCode(e.getErrCode());
        } catch (Exception ex) {
			BankLogUtils.printServiceImplExceptionLog(ex);
			result.setResultCode(ProcCodeConstants.PROC_CODE_100E6058);
		}
        return result;
    }

    @Override
    public Result certification(ExPayBaseMessage baseMsg) {
        Result result = new Result(false);
        CiticExpay citicExpay = new CiticExpay();
        BeanUtils.copyProperties(baseMsg, citicExpay);
        try {
            CiticExpayResMessage resMessage = (CiticExpayResMessage) citicExPayManage.certification(citicExpay);

            if (resMessage.isSuccess()) {

                CiticExpayCerResMessage cerResMsg = resMessage.getExpayMessage().getCerResMessage();
                /**
                 * 0 - 鉴权成功,正常报文只返回一个编码
                 */
                if (CiticConstants.EXPAY_RECODE_SUCCESS.equals(cerResMsg.getRetCode())) {
                    result.setModel("flag", true);
                } else {
                    result.setModel("flag", false);
                    result.setModel("retMsg", resMessage.getExpayMessage().getCerResMessage().getRetMsg());
                }
            } else {
                result.setModel("flag", false);
                result.setModel("retMsg", resMessage.getExpayMessage().getErrorMessage().getRetMsg());
            }
            result.setSuccess(true);
        } catch (GopayException e) {
            BankLogUtils.printServiceImplExceptionLog(e);
            result.setResultCode(e.getErrCode());
        } catch (Exception ex) {
            BankLogUtils.printServiceImplExceptionLog(ex);
            result.setResultCode(ProcCodeConstants.PROC_CODE_100E6076);
        }
        return result;
    }

    @Override
    public Result sendSms(ExPayBaseMessage baseMsg) {
        Result result = new Result(false);
        CiticExpay message = new CiticExpay();
        BeanUtils.copyProperties(baseMsg, message);
        try {
            Map<String, String> smsRes = smsController.sendSMS(message);
            if (ProcCodeConstants.PROC_CODE_100E6102.equals(smsRes.get("resCode"))) {
                // 短信发送成功
                result.setModel("flag", true);
            } else {
                // 短信发送失败
                result.setModel("flag", false);
            }
            result.setModel("sendCount", smsRes.get("sendCount"));
            result.setModel("retMsg", smsRes.get("retMsg"));
            result.setModel("resCode", smsRes.get("resCode"));
            result.setResultCode(smsRes.get("resCode"));
            result.setSuccess(true);
        } catch (Exception ex) {
            BankLogUtils.printServiceImplExceptionLog(ex);
            result.setResultCode(ProcCodeConstants.PROC_CODE_100E6077);
        }
        return result;
    }

    @Override
    public Result checkSms(ExPayBaseMessage baseMsg) {
        Result result = new Result(false);
        CiticExpay message = new CiticExpay();
        BeanUtils.copyProperties(baseMsg, message);
        try {
            Map<String, String> smsRes = smsController.checkSMS(message);
            if (ProcCodeConstants.PROC_CODE_100E6091.equals(smsRes.get("resCode"))) {
                // 验证通过
                result.setModel("flag", true);
            } else {
                // 验证失败
                result.setModel("flag", false);
                if (!ProcCodeConstants.PROC_CODE_100E6099.equals(smsRes.get("resCode"))) {
                    Map<String, String> freezeRes = smsController.freezeCard(message);
                    if (freezeRes != null)
                        smsRes = freezeRes;
                }
            }
            result.setModel("failCount", smsRes.get("failCount"));
            result.setModel("retMsg", smsRes.get("retMsg"));
            result.setModel("resCode", smsRes.get("resCode"));
            result.setResultCode(smsRes.get("resCode"));
            result.setSuccess(true);
        } catch (Exception ex) {
            BankLogUtils.printServiceImplExceptionLog(ex);
            result.setResultCode(ProcCodeConstants.PROC_CODE_100E6078);
        }
        return result;

    }

    @Override
    public Result queryCvn(ExPayBaseMessage baseMsg) {
        // TODO Auto-generated method stub
        return null;
    }

    public SmsSupportController getSmsController() {
        return smsController;
    }

    public void setSmsController(SmsSupportController smsController) {
        this.smsController = smsController;
    }

    /**
     * 查询是否需要调用鉴权接口
     */
    public Result queryNeedCert(ExPayBaseMessage baseMsg) {
        Result result = new Result();
        result.setSuccess(true);
        result.setModel("NeedMark", QueryNeedCertConstants.QUERY_RESULT_NONEED);
        return result;
    }
    /*
     * @Override public Result refundQuery(ExPayBaseMessage baseMsg) { // TODO
     * Auto-generated method stub return null; }
     */

    @Override
    public Result refundBack(ExPayBaseMessage baseMsg) {
        // TODO Auto-generated method stub
        return null;
    }
}
